/*
					ORDENACAO DE VETOR UTILIZANDO SOCKETS EM C
 =======================================================================================
 Nome        : NivelInf.c
 Autores     : Eduardo Aramizu, Matheus Zoccoler
 Disciplina  : SSC0640 – Sistemas Computacionais Distribuídos (Engenharia de Computacao)
 Descricao   : O arquivo NivelInf.c define o funcionamento dos nos do 1 nivel do cluster
				Cada no gera um vetor aleatorio de inteiros de tamanho 125. O no entao 
				se comunica com o no superior e envia o vetor desordenado. Por fim, o
				programa espera o recebimento do vetor de tamanho 1000 ja ordenado.
 =======================================================================================
 */
#ifndef ALL_H_INCLUDED
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>   // Definicao de tipos
#include <sys/socket.h>  // Biblioteca de estrutara de sockets
#include <netinet/in.h>  // Define os padroes de protocolo IP
#include <arpa/inet.h>   // Converte enderecos hosts
#include <string.h>
#include <unistd.h> // Define constantes POSIX
#include <errno.h>  // Utilizado para capturar mensagens de erro
#include <netdb.h>
#define ALL_H_INCLUDED
#endif

#ifndef OPERATIONS_H_INCLUDED
#include "Operacoes.h"
#endif

#define SNDSIZE 125
#define TOTSIZE 1000

int main(int argc, char *argv[])
{
    int sock, connected, bytes_recv, i, true = 1;
    struct sockaddr_in server_addr;
    int sndArray[SNDSIZE], totArray[TOTSIZE];
    struct hostent *host;

    struct timeval t1,t2,t3,t4;
    int time;
    FILE *f;
    f = fopen(argv[3], "w");

    gettimeofday(&t2, 0);   //Tempo inicio execucao do programa

    /********** GERA VETOR ALEATORIO ************/
    randomVector(sndArray, SNDSIZE);

    /*for(i=0; i<SNDSIZE; i++)
        printf("%d\n", sndArray[i]);*/

    /********** CONECTA COM NIVEL SUP ************/
    host = gethostbyname(argv[1]);

    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        perror("Erro no Socket");
        exit(1);
    }

    // Configura o endereco de destino
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = ntohs(atoi(argv[2]));
    server_addr.sin_addr = *((struct in_addr *)host->h_addr);
    bzero(&(server_addr.sin_zero),8);

    if (connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
    {
        perror("Erro de conexao");
        exit(1);
    }

    /********** ENVIA AO NIVEL SUP ************/
    gettimeofday(&t1, 0);   //Tempo antes do send
    // Funcao send(int socket, void*buffer, size_t size, int flags)
    send(sock, sndArray, SNDSIZE*4, 0);
    gettimeofday(&t2, 0);   //Tempo depois do send
    time = t2.tv_usec-t1.tv_usec;
    fprintf(f,"\nTempo envio para %s:  %.2dus.\n", argv[1], time);

    printf("Mensagem enviada para %s na porta %s.\n", argv[1], argv[2]);

    /********** RECEBE DO NIVEL SUP ************/
    gettimeofday(&t1, 0);   //Tempo antes do receive
    // Funcao recv (int socket, void *buffer, size_t size, int flags)
    if( bytes_recv = recv(sock, totArray, TOTSIZE*4, MSG_WAITALL) != 0)
        printf("\n Mensagem recebida: \n");
    else
        printf("\n Erro ao receber mensagem. \n");
    gettimeofday(&t2, 0);   //Tempo depois do receive
    time = t2.tv_usec-t1.tv_usec;
    fprintf(f,"\nTempo recebimento de %s:  %.2dus.\n", argv[1], time);

    /*for(i=0; i<TOTSIZE; i++)
        printf("%d\n", totArray[i]);*/

    //Fecha conexao com superior
    close(sock);

    fclose(f);

    gettimeofday(&t3, 0);   //Tempo fim execucao do programa
    time = t3.tv_usec-t2.tv_usec;
    fprintf(f,"\nTempo total:  %.2dus.\n",time);

    return 0;
}
